package com.winbomb.kingcard.base;

import java.util.Arrays;

import com.winbomb.kingcard.GameMsg;
import com.winbomb.kingcard.IBattle;
import com.winbomb.kingcard.ICard;
import com.winbomb.kingcard.ICardPile;
import com.winbomb.kingcard.IGameLogic;
import com.winbomb.kingcard.IGameRecord;
import com.winbomb.kingcard.INegotiate;
import com.winbomb.kingcard.IPlayer;
import com.winbomb.kingcard.IPlayerInfo;
import com.winbomb.kingcard.IState;
import com.winbomb.kingcard.Suit;
import com.winbomb.kingcard.base.ai.AIThread;
import com.winbomb.kingcard.framework.Game;
import com.winbomb.kingcard.screens.util.Render;

public class GameLogic implements IGameLogic {

	public static final String TAG = "GameImpl";

	/** 最多游戏人数 */
	public static final int MAX_PLAYER_COUNT = 12;

	/** 入座的次序 */
	private static final int[] SEAT_SEQ = new int[] { 0, 6, 2, 8, 4, 10, 1, 7, 3, 9, 5, 11 };

	private static final String[] PLAYER_NAMES = new String[] { "秦王", "齐王", "楚王", "燕王", "赵王", "韩王", "魏王", "戎主", "匈奴王",
			"羌王", "越王", "宋王" };

	/** 对Game的引用 */
	private Game game;

	/** 开始起到手中牌的数量 */
	public static final int INIT_CARD_COUNT = 8;

	/** 手中最大能拥有的牌的数量 */
	public static final int MAX_CARD_COUNT = 99;

	/** 一次最多的出牌数 */
	public static final int MAX_PLAY_CARD = 5;

	/** 路过人家领地时提供选择的牌数 */
	public static final int MAX_OFFER_SIZE = 3;

	/** 玩家 */
	private IPlayer[] players;

	/** 牌堆 */
	private ICardPile cardPile;

	/** 当前出牌玩家 */
	private IPlayer currPlayer;

	/** 当前回合所属玩家 */
	private IPlayer currTurn;

	/** 当前庄家 */
	private IPlayer currBanker;

	/** 当前要复苏的玩家 */
	private IPlayer tributary;

	/** 游戏的进展情况 */
	private IState state;

	/** 游戏信息记录器 */
	private IGameRecord gameReocrder;

	/** 渲染管理器 */
	private Render render;

	/** 动画管理器 */
	private AnimManager animManager;

	/** 战争管理器 */
	private IBattle battle;

	/** 交涉管理器 */
	private INegotiate negotiate;

	/** AI线程 */
	private AIThread aiThread;

	/** 游戏是否处于暂停状态 */
	private boolean isPaused;

	/** 是否已经停止 */
	private boolean isStopped;

	/** 游戏回合数 */
	private int roundCnt;

	/** 游戏消耗时间 */
	private float timeCost;

	/** 游戏是否结束 */
	private boolean isGameOver;

	/** 奖金 */
	private int bonus;

	public GameLogic(Game game, int playerCnt) {
		players = new IPlayer[playerCnt];
		cardPile = new CardPile((players.length + 3) / 4);

		IPlayerInfo playerInfo = new PlayerInfo(PLAYER_NAMES[0], 0);
		players[0] = new Player(this, playerInfo, true);

		int[] seats = new int[players.length];
		for (int i = 0; i < seats.length; i++) {
			seats[i] = SEAT_SEQ[i];
		}
		Arrays.sort(seats);

		for (int i = 1; i < seats.length; i++) {
			playerInfo = new PlayerInfo(PLAYER_NAMES[i], seats[i]);
			players[i] = new Player(this, playerInfo, false);
			players[i].setPlayerIndex(i);
		}

		currTurn = players[0];
		currBanker = players[0];
		currPlayer = currTurn;
		tributary = null;
		battle = new Battle(this);
		negotiate = new Negotiate();
		gameReocrder = new GameRecorder();

		this.game = game;
		this.render = new Render(this, game.getGraphics());
		this.animManager = new AnimManager(this);

		aiThread = new AIThread(this);
		new Thread(aiThread, "AIThread " + System.currentTimeMillis()).start();
	}

	@Override
	public IPlayer[] getPlayers() {
		return players;
	}

	@Override
	public int getPlayerCount() {
		return players.length;
	}

	@Override
	public void start() {
		this.isPaused = true;
		this.isStopped = false;
		this.isGameOver = false;
		this.roundCnt = 1;
		this.timeCost = 0f;
		this.bonus = players.length * 5;
		cardPile.initPile();

		for (IPlayer player : players) {
			player.reset();
		}

		currTurn = players[0];
		currPlayer = currTurn;
		gameReocrder.clearMessage();
		setState(GameState.GAME_START);

		// testScenrio();

		this.isPaused = false;
		this.aiThread.work();

	}

	/**
	 * 测试场景
	 */
	private void testScenrio() {

		// 制作帮组的场景
		players[1].setAttackTarget(players[0]);
		players[0].defeated();
		players[0].revitalize(players[1], new ICard[] {});

		// players[0].setAttackTarget(players[2]);
		// players[2].defeated();

		players[1].setAttackTarget(null);
		players[0].setAttackSource(null);

		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < players.length; j++) {
				if (!players[j].isAlive()) {
					continue;
				}

				if (j != 0 || (j == 0 && i >= 5)) {
					players[j].drawCard();
				}
			}
		}

		((Player) players[0]).insertCard(new Card(14, Suit.BLACK));
		((Player) players[0]).insertCard(new Card(15, Suit.RED));

		// players[1].setAttackTarget(players[0]);
		// players[0].defeated();
		// players[0].revitalize(players[1], new ICard[] {});
		//
		// for (int i = 0; i < 8; i++) {
		// players[0].drawCard();
		// players[1].drawCard();
		// ((Player) players[0]).insertCard(new Card(12, Suit.SPADE));
		// ((Player) players[1]).insertCard(new Card(12, Suit.HEART));
		// for (int j = 0; j < players.length; j++) {
		// players[j].drawCard();
		// }

		// for (int j = 0; j < 11; j++) {
		// players[j].drawCard();
		// }
		// }

		// players[0].drawCard();
		// players[0].revitalize(players[1], new ICard[] {});
		//
		// for (int i = 0; i < 9; i++) {
		// players[11].drawCard();
		// }

		currTurn = players[6];

		// setState(GameState.SELECT_ACTION);
		nextTurn();

		//
		// for (int i = 0; i < 5; i++) {
		// players[0].selectCard(i);
		// players[1].selectCard(i);
		// }
		//
		// players[0].setAttackTarget(players[1]);
		// battle.newBattle(players[0], players[1]);
		// battle.start();
		//
		// setState(BattleState.BATTLE_START);

		// 场景2
		// for (int i = 0; i < 12; i++) {
		// players[0].drawCard();
		// players[1].drawCard();
		// }
		//
		// players[1].setAttackTarget(players[2]);
		// players[2].defeated();
		//
		// setState(GameState.SELECT_ACTION);

		// int[] cardCnt = new int[] { 30, 18, 10, 10, 10, 4, 30, 4, 4, 4, 4, 4
		// };
		//
		// for (int i = 0; i < players.length; i++) {
		// for (int j = 0; j < cardCnt[i]; j++) {
		// players[i].drawCard();
		// }
		// }
		//
		// currTurn = players[11];
		// currPlayer = currTurn;
		// setState(GameState.SELECT_ACTION);
	}

	@Override
	public void stop() {
		this.isStopped = true;
	}

	@Override
	public boolean isStopped() {
		return this.isStopped;
	}

	@Override
	public IPlayer getCurrPlayer() {
		return currPlayer;
	}

	@Override
	public void setCurrPlayer(IPlayer player) {
		this.currPlayer = player;
		this.currPlayer.setDone(false);
	}

	@Override
	public IPlayer getCurrTurn() {
		return currTurn;
	}

	@Override
	public IPlayer getCurrBanker() {
		return players[0];
	}

	@Override
	public IState getState() {
		return state;
	}

	@Override
	public void setState(IState state) {
		this.state = state;
	}

	@Override
	public IBattle getBattle() {
		return battle;
	}

	@Override
	public INegotiate getNegotiate() {
		return negotiate;
	}

	@Override
	public ICardPile getCardPile() {
		return cardPile;
	}

	public void nextStep() {
		state.nextState(this);
		getCurrPlayer().setDone(false);
		getCurrPlayer().setTimeLeft(30);
		aiThread.work();
	}

	@Override
	public boolean nextTurn() {

		// 将Player切换到下一个Player
		currTurn = currTurn.getRightPlayer();
		boolean isNewRound = (currTurn == currBanker);
		while (!currTurn.isAlive()) {
			currTurn = currTurn.getRightPlayer();
			if (currTurn == currBanker) {
				isNewRound = true;
			}
		}

		// 对于主公: 只要有附属势力,就可以派遣.
		// 只要有存活的附属势力,就可以征召
		boolean[] actionMask = currTurn.getActionMask();
		for (int i = 0; i < actionMask.length; i++) {
			actionMask[i] = false;
		}
		actionMask[0] = true;
		actionMask[1] = true;

		if (currTurn.getMaster() == currTurn) {
			for (IPlayer player : players) {
				if (player.getMaster() == null || (player.getMaster() == currTurn && player != currTurn)) {
					actionMask[2] = true;

					if (player.isAlive()) {
						actionMask[3] = true;
					}
				}
			}

		}

		// 要同时拥有大小王才能够独立
		if (currTurn.getMaster() != currTurn) {
			ICard[] cards = currTurn.getCards();
			boolean hasRedJoker = false, hasBlackJoker = false;
			for (ICard card : cards) {
				if (card.isRedJoker()) {
					hasRedJoker = true;
				} else if (card.isBlackJoker()) {
					hasBlackJoker = true;
				}
			}

			actionMask[4] = (hasRedJoker && hasBlackJoker);
		}

		currPlayer = currTurn;
		tributary = null;

		if (state != GameState.GAME_START) {
			if (isNewRound) {
				roundCnt++;

				// 记录消息
				gameReocrder.clearMessage();
				GameMsg msg = new GameMsg(0);
				msg.add("进入第 " + roundCnt + " 回合.");
				gameReocrder.add(msg);
			}
		}

		return isNewRound;
	}

	@Override
	public IPlayer getTributary() {
		return tributary;
	}

	@Override
	public void setTributary(IPlayer player) {
		this.tributary = player;
	}

	@Override
	public IGameRecord getGameRecorder() {
		return this.gameReocrder;
	}

	public AnimManager getAnimManager() {
		return this.animManager;
	}

	public Render getRender() {
		return this.render;
	}

	public Game getGame() {
		return this.game;
	}

	@Override
	public boolean isPaused() {
		return this.isPaused;
	}

	@Override
	public void setPause(boolean isPause) {
		this.isPaused = isPause;
	}

	@Override
	public int getRoundCount() {
		return this.roundCnt;
	}

	@Override
	public float getTimeCost() {
		return this.timeCost;
	}

	@Override
	public void step(float dt) {
		this.timeCost += dt;
	}

	@Override
	public IPlayer getWinner() {
		if (!isGameOver) {
			return null;
		}

		for (IPlayer player : players) {
			if (player.getMaster() == player) {
				return player;
			}
		}

		return null;
	}

	@Override
	public boolean isGameOver() {
		// 如果最后所有的势力都统一为一个势力,那么游戏结束
		int forceCnt = 0;
		for (IPlayer player : players) {
			if (player.getMaster() == player) {
				forceCnt++;
			}
		}

		isGameOver = (forceCnt == 1);
		return isGameOver;
	}

	@Override
	public void addBonus(int bonus) {
		this.bonus += bonus;
	}

	@Override
	public int getBonus() {
		return this.bonus;
	}

}
